<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>

    <link href="./static/css/bootstrap.min.css" rel="stylesheet" />
    <link href="./static/css/style.css" rel="stylesheet" />
    <link href="./static/css/font-awesome.min.css" rel="stylesheet" />
    <link href="./static/jquery-layout/jquery.layout-latest.css" rel="stylesheet" />

    <script src="./static/js/jquery.min.js"></script>
    <script src="./static/js/bootstrap.min.js"></script>
    <script src="./static/js/x6.js"></script>
    <script src="./static/js/x6-node.js"></script>
    <script src="./static/jquery-layout/jquery.layout-latest.js"></script>
    <script src="./static/layer/layer.min.js"></script>

    <style type="text/css">
        
    </style>
</head>
<body>
    <div class="ui-layout-north">
        <div id="toolbar">
            <button class="btn btn-sm btn-primary" onclick="getJson()"><i class="fa fa-save"></i> 获取文件结构</button>
            <button class="btn btn-sm btn-primary" onclick="before()"><i class="fa fa-undo"></i> 撤销</button>
            <button class="btn btn-sm btn-primary" onclick="next()"><i class="fa fa-repeat"></i> 重做</button>
            <button class="btn btn-sm btn-primary" onclick="savePng()"><i class="fa fa-file-image-o"></i> 保存png</button>
        </div>
    </div>
    <div class="ui-layout-west">
        <div id="stencil"></div>
    </div>
    <div class="ui-layout-center">
        <div id="graph-container" style="width: 100%;height: 100%"></div>
    </div>
    
    
    <script>
        $(function() {
            var panehHidden = false;
            if ($(this).width() < 769) {
                panehHidden = true;
            }
            $('body').layout({ initClosed: panehHidden, west__size: 185 });
    
        });
        // #region 初始化画布
        const graph = new X6.Graph({
            container: document.getElementById('graph-container'),
            width: 1800,
            height: 1000,
            grid: true,
            mousewheel: {       //按住 ctrl键鼠标滚轮控制放大缩小
                enabled: true,
                zoomAtMousePosition: true,
                modifiers: 'ctrl',
                minScale: 0.5,
                maxScale: 3,
            },
            connecting: {
                snap: true,
                allowBlank: false,
                allowLoop: false,
                highlight: true,
                router: {
                    name: 'manhattan',       //连接线根据位置自动换节点
                    args: {
                        padding: 1,
                    },
                },
                connector: {
                    name: 'rounded',
                    args: {
                        radius: 8,
                    },
                },
                anchor: 'center',
                connectionPoint: 'anchor',
                allowBlank: false,
                snap: {
                    radius: 20,
                },
                createEdge() {
                    return new X6.Shape.Edge({
                        attrs: {
                            line: {
                                stroke: '#A2B1C3',
                                strokeWidth: 2,
                                targetMarker: {
                                    name: 'block',
                                    width: 12,
                                    height: 8,
                                },
                            },
                        },
                        zIndex: 0,
                    })
                },
                validateConnection({ targetMagnet }) {
                    return !!targetMagnet
                },
            },
            highlighting: {
                magnetAdsorbed: {
                    name: 'stroke',
                    args: {
                        attrs: {
                            fill: '#5F95FF',
                            stroke: '#5F95FF',
                        },
                    },
                },
            },
            resizing: true,
            rotating: false,
            selecting: {
                enabled: true,
                rubberband: true,
                showNodeSelectionBox: true,
            },
            snapline: true,
            keyboard: true,
            clipboard: true,
            history: {
                enabled: true,
                ignoreAdd: true,
                ignoreRemove: true,
                ignoreChange: false,
            },
        })
        // #endregion
    
        // #region 初始化 stencil
        const stencil = new X6.Addon.Stencil({
            title: '流程图',
            target: graph,
            stencilGraphWidth: 200,
            stencilGraphHeight: 500,
			collapsable: false,
            groups: [
                {
                    title: '基础流程图',
                    name: 'flow',
                },
            ],
            layoutOptions: {
                columns: 1,
                columnWidth: 120,
                rowHeight: 80,
            },
        })
        document.getElementById('stencil').appendChild(stencil.container)
        // #endregion
    
        // #region 快捷键与事件
        // copy cut paste
        graph.bindKey(['meta+c', 'ctrl+c'], () => {
            const cells = graph.getSelectedCells()
            if (cells.length) {
                graph.copy(cells)
            }
            return false
        })
        graph.bindKey(['meta+x', 'ctrl+x'], () => {
            const cells = graph.getSelectedCells()
            if (cells.length) {
                graph.cut(cells)
            }
            return false
        })
        graph.bindKey(['meta+v', 'ctrl+v'], () => {
            if (!graph.isClipboardEmpty()) {
                const cells = graph.paste({ offset: 32 })
                graph.cleanSelection()
                graph.select(cells)
            }
            return false
        })
    
        //undo redo
        graph.bindKey(['meta+z', 'ctrl+z'], () => {
            if (graph.history.canUndo()) {
                graph.history.undo()
            }
            return false
        })
        graph.bindKey(['meta+shift+z', 'ctrl+shift+z'], () => {
            if (graph.history.canRedo()) {
                graph.history.redo()
            }
            return false
        })
    
        // select all
        graph.bindKey(['meta+a', 'ctrl+a'], () => {
            const nodes = graph.getNodes()
            if (nodes) {
                graph.select(nodes)
            }
        })
    
        //delete
        graph.bindKey('delete', () => {
            const cells = graph.getSelectedCells()
            if (cells.length) {
                graph.removeCells(cells)
            }
        })
    
        // zoom
        graph.bindKey(['ctrl+1', 'meta+1'], () => {
            const zoom = graph.zoom()
            if (zoom < 1.5) {
                graph.zoom(0.1)
            }
        })
        graph.bindKey(['ctrl+2', 'meta+2'], () => {
            const zoom = graph.zoom()
            if (zoom > 0.5) {
                graph.zoom(-0.1)
            }
        })
    
        //鼠标浮动，删除按钮
        /*graph.on('node:mouseenter', ({ node }) => {
            node.addTools({
                name: 'button-remove',
                args: {
                    x: 0,
                    y: 0,
                    offset: { x: 10, y: 10 },
                },
            })
        })
        graph.on('node:mouseleave', ({ node }) => {
            node.removeTools()
        })*/
    
        //鼠标右击事件
        graph.on('node:contextmenu', ({ node }) => {
            console.log(node.id);
            layer.msg(node.id);
        })
        //双击修改内容
        graph.on('cell:dblclick', ({ cell, e }) => {
            const isNode = cell.isNode()
            const name = cell.isNode() ? 'node-editor' : 'edge-editor'
            cell.removeTool(name)
            cell.addTools({
                name,
                args: {
                    event: e,
                    attrs: {
                        backgroundColor: isNode ? '#EFF4FF' : '#FFF',
                    },
                },
            })
        })
    
        // 控制连接桩显示/隐藏
        const showPorts = (ports, show) => {
            for (let i = 0, len = ports.length; i < len; i = i + 1) {
                ports[i].style.visibility = show ? 'visible' : 'hidden'
            }
        }
        graph.on('node:mouseenter', () => {
            const container = document.getElementById('graph-container')
            const ports = container.querySelectorAll(
                '.x6-port-body',
            )
            showPorts(ports, true)
        })
        graph.on('node:mouseleave', () => {
            const container = document.getElementById('graph-container')
            const ports = container.querySelectorAll(
                '.x6-port-body',
            )
            showPorts(ports, false)
        })
    
        graph.on('edge:mouseenter', ({ edge }) => {
            edge.addTools([
                'source-arrowhead',
                'target-arrowhead',
                {
                    name: 'button-remove',
                    args: {
                        distance: -30,
                    },
                },
            ])
        })
        graph.on('edge:mouseleave', ({ edge }) => {
            edge.removeTools()
        })
    
        // #endregion
    
        const start = graph.createNode({
            shape: 'start-node',
            label: '开始',
            attrs: {
                body: {
                    strokeWidth: 1,
                    stroke: '#00FF00',
                    fill: '#EFF4FF',
                },
            },
        })
    
        const activity = graph.createNode({
            shape: 'activity',
            label: '人员处理节点',
            width: 100,
            height: 60,
            attrs: {
                img: {
                    x: 6,
                    y: 6,
                    width: 16,
                    height: 16,
                    xlinkHref:'./static/images/people.png',
                },
            }
        })
    
        const end = graph.createNode({
            shape: 'end-node',
            label: '结束',
            attrs: {
                body: {
                    strokeWidth: 2,
                    stroke: '#ff0000',
                    fill: '#EFF4FF',
                },
            },
        })
    
        const judge = graph.createNode({
            shape: 'gateway',
            width: 60,
            height: 60,
        })
        stencil.load([start, activity, end], 'flow')
    
        function changeHitory()
        {
            if (graph.isHistoryEnabled()) {
                graph.disableHistory()
            } else {
                graph.enableHistory()
            }
        }
    
        //获取连线数据
        function getJson()
        {
            console.log(graph.toJSON());
        }
        function before()
        {
            graph.undo();
        }
        function next()
        {
            graph.redo();
        }
        function savePng()
        {
            graph.toPNG((dataUri) => {
                console.log(dataUri);
                // 下载
                DataUri.downloadDataUri(dataUri, 'chart.png');
            })
        }
    </script>
</body>
</html>